void disable_intremap(struct iommu *iommu)
{
u32 sts;
+ u64 irta;
unsigned long flags;
if ( !ecap_intr_remap(iommu->ecap) )
return;
+ spin_lock_irqsave(&iommu->register_lock, flags);
+ sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
+ if ( !(sts & DMA_GSTS_IRES) )
+ goto out;
+
+ dmar_writel(iommu->reg, DMAR_GCMD_REG, sts & (~DMA_GCMD_IRE));
+
+ IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
+ !(sts & DMA_GSTS_IRES), sts);
+
/* If we are disabling Interrupt Remapping, make sure we dont stay in
* Extended Interrupt Mode, as this is unaffected by the Interrupt
* Remapping flag in each DMAR Global Control Register.
* in x2apic mode. Any code turning interrupt remapping back on will set
* EIME back correctly.
*/
- if ( iommu_supports_eim() )
- {
- u64 irta;
- irta = dmar_readl(iommu->reg, DMAR_IRTA_REG);
- dmar_writel(iommu->reg, DMAR_IRTA_REG, irta & ~IRTA_EIME);
- IOMMU_WAIT_OP(iommu, DMAR_IRTA_REG, dmar_readl,
- !(irta & IRTA_EIME), irta);
- }
+ if ( !ecap_eim(iommu->ecap) )
+ goto out;
- spin_lock_irqsave(&iommu->register_lock, flags);
- sts = dmar_readl(iommu->reg, DMAR_GSTS_REG);
- if ( !(sts & DMA_GSTS_IRES) )
+ /* Can't read the register unless we ecaps says we can */
+ irta = dmar_readl(iommu->reg, DMAR_IRTA_REG);
+ if ( !(irta & IRTA_EIME) )
goto out;
- dmar_writel(iommu->reg, DMAR_GCMD_REG, sts & (~DMA_GCMD_IRE));
+ dmar_writel(iommu->reg, DMAR_IRTA_REG, irta & ~IRTA_EIME);
+ IOMMU_WAIT_OP(iommu, DMAR_IRTA_REG, dmar_readl,
+ !(irta & IRTA_EIME), irta);
- IOMMU_WAIT_OP(iommu, DMAR_GSTS_REG, dmar_readl,
- !(sts & DMA_GSTS_IRES), sts);
out:
spin_unlock_irqrestore(&iommu->register_lock, flags);
}